
#include "my_crc.h"
#include "my_crc_code.h"

uint32_t Crc32;
uint32_t DatLen;

bool myserial_CmdCrc(QByteArray &CmdBuff, int CmdSize)
{
    int iCnt;
    int Crc16b = 0xFFFF;
    uint8_t  TmpCrc;

    // Cacl CRC
    for(iCnt=0; iCnt<CmdSize; iCnt++)
    {
        TmpCrc = (Crc16b >> 0) & 0xFF;
        Crc16b = (Crc16b >> 8) ^ SERIAL_CRC16_TABLE[(TmpCrc ^ CmdBuff[iCnt]) & 0xFF];
    }
    // Insert CRC Into Buff
    CmdBuff[CmdSize+0] = (Crc16b >> 0) & 0xFF;
    CmdBuff[CmdSize+1] = (Crc16b >> 8) & 0xFF;

    return true;
}
uint8_t myserial_EccCalc(QByteArray CmdBuff)
{
    uint8_t  CmdEcc;
    uint32_t CmtBits;

    // Load Command
    CmtBits = 0;
    CmtBits = (CmtBits << 0) | (CmdBuff.at(2)&0xFF);
    CmtBits = (CmtBits << 8) | (CmdBuff.at(1)&0xFF);
    CmtBits = (CmtBits << 8) | (CmdBuff.at(0)&0xFF);
    // Cacl Ecc
    CmdEcc = 0;
    // Bit.7
    CmdEcc = (CmdEcc << 0) | 0x00;
    // Bit.6
    CmdEcc = (CmdEcc << 1) | 0x00;
    // Bit.5
    CmdEcc = (CmdEcc << 1) | (0x01 & ((CmtBits>>10 & 0x01) ^ (CmtBits>>11 & 0x01) ^ (CmtBits>>12 & 0x01) ^ (CmtBits>>13 & 0x01) ^ (CmtBits>>14 & 0x01) ^ \
                                      (CmtBits>>15 & 0x01) ^ (CmtBits>>16 & 0x01) ^ (CmtBits>>17 & 0x01) ^ (CmtBits>>18 & 0x01) ^ (CmtBits>>19 & 0x01) ^ \
                                      (CmtBits>>21 & 0x01) ^ (CmtBits>>22 & 0x01) ^ (CmtBits>>23 & 0x01)));
    // Bit.4
    CmdEcc = (CmdEcc << 1) | (0x01 & ((CmtBits>>4  & 0x01) ^ (CmtBits>>5  & 0x01) ^ (CmtBits>>6  & 0x01) ^ (CmtBits>>7  & 0x01) ^ (CmtBits>>8  & 0x01) ^ \
                                      (CmtBits>>9  & 0x01) ^ (CmtBits>>16 & 0x01) ^ (CmtBits>>17 & 0x01) ^ (CmtBits>>18 & 0x01) ^ (CmtBits>>19 & 0x01) ^ \
                                      (CmtBits>>20 & 0x01) ^ (CmtBits>>22 & 0x01) ^ (CmtBits>>23 & 0x01)));
    // Bit.3
    CmdEcc = (CmdEcc << 1) | (0x01 & ((CmtBits>>1  & 0x01) ^ (CmtBits>>2  & 0x01) ^ (CmtBits>>3  & 0x01) ^ (CmtBits>>7  & 0x01) ^ (CmtBits>>8  & 0x01) ^ \
                                      (CmtBits>>9  & 0x01) ^ (CmtBits>>13 & 0x01) ^ (CmtBits>>14 & 0x01) ^ (CmtBits>>15 & 0x01) ^ (CmtBits>>19 & 0x01) ^ \
                                      (CmtBits>>20 & 0x01) ^ (CmtBits>>21 & 0x01) ^ (CmtBits>>23 & 0x01)));
    // Bit.2
    CmdEcc = (CmdEcc << 1) | (0x01 & ((CmtBits>>0  & 0x01) ^ (CmtBits>>2  & 0x01) ^ (CmtBits>>3  & 0x01) ^ (CmtBits>>5  & 0x01) ^ (CmtBits>>6  & 0x01) ^ \
                                      (CmtBits>>9  & 0x01) ^ (CmtBits>>11 & 0x01) ^ (CmtBits>>12 & 0x01) ^ (CmtBits>>15 & 0x01) ^ (CmtBits>>18 & 0x01) ^ \
                                      (CmtBits>>20 & 0x01) ^ (CmtBits>>21 & 0x01) ^ (CmtBits>>22 & 0x01)));
    // Bit.1
    CmdEcc = (CmdEcc << 1) | (0x01 & ((CmtBits>>0  & 0x01) ^ (CmtBits>>1  & 0x01) ^ (CmtBits>>3  & 0x01) ^ (CmtBits>>4  & 0x01) ^ (CmtBits>>6  & 0x01) ^ \
                                      (CmtBits>>8  & 0x01) ^ (CmtBits>>10 & 0x01) ^ (CmtBits>>12 & 0x01) ^ (CmtBits>>14 & 0x01) ^ (CmtBits>>17 & 0x01) ^ \
                                      (CmtBits>>20 & 0x01) ^ (CmtBits>>21 & 0x01) ^ (CmtBits>>22 & 0x01) ^ (CmtBits>>23 & 0x01)));
    // Bit.0
    CmdEcc = (CmdEcc << 1) | (0x01 & ((CmtBits>>0  & 0x01) ^ (CmtBits>>1  & 0x01) ^ (CmtBits>>2  & 0x01) ^ (CmtBits>>4  & 0x01) ^ (CmtBits>>5  & 0x01) ^ \
                                      (CmtBits>>7  & 0x01) ^ (CmtBits>>10 & 0x01) ^ (CmtBits>>11 & 0x01) ^ (CmtBits>>13 & 0x01) ^ (CmtBits>>16 & 0x01) ^ \
                                      (CmtBits>>20 & 0x01) ^ (CmtBits>>21 & 0x01) ^ (CmtBits>>22 & 0x01) ^ (CmtBits>>23 & 0x01)));

    return CmdEcc;
}
// 校验DL命令
bool myserial_Cmd_Check(QByteArray data)
{
    if(data.size() < 10)
    {
        return false;
    }
    {// 校验Ecc
        QByteArray TempNum;
        uint8_t CalcEcc;
        TempNum.append(data.at(6));    //code
        TempNum.append(data.at(7));    //size.lsb
        TempNum.append(data.at(8));    //size.msb
        CalcEcc = myserial_EccCalc(TempNum);
        if(CalcEcc != data.at(9))
        {
            return false;
        }
    }
    {// 校验Crc
        int DataSize = data.size()-10;
        if(DataSize > 0)
        {
            // 得到本身的CRC
            QByteArray CalcCrc;
            CalcCrc.clear();
            CalcCrc.append(data.mid(8+DataSize,2));
            // 计算CRC
            QByteArray TempCrc;
            TempCrc.clear();
            TempCrc.append(data.mid(10, DataSize));
            TempCrc.append(2, char(0));
            myserial_CmdCrc(TempCrc, DataSize);
            // 比较CRC
            if(CalcCrc.mid(0,2) != TempCrc.mid(DataSize-2,2))
            {
                return false;
            }
        }
    }
    return true;
}

//校验和
uint16_t crc16_result(QByteArray x,uint16_t x_size)
{
    uint16_t result,icnt;
    result = 0xFF;
    for(icnt = 0;icnt < x_size;icnt++)
    {
        result += (((uint16_t)(x.at(icnt)&0x00FF)));
    }
    return result;
}
//生成随机数
void generateRandomNumber(QByteArray &arr,int iArrLen)
{
    for(int iRandom = 0;iRandom < iArrLen; iRandom++)
    {
        //随机生成0到254的随机数
        arr.append( (uchar) (rand()%253 + 1) );
    }
}
// 校验F210命令
bool F210_Cmd_Check(QByteArray data)
{
    // 长度校验
    if(data.size() < PORT_SIZE_MAX_F210)
    {
        return false;
    }
    QByteArray ReadBuff;
    ReadBuff.resize(PORT_SIZE_MAX_F210);
    ReadBuff = data.mid(0, PORT_SIZE_MAX_F210);
    //校验CRC，若不成功则发送重复请求
    uint16_t AddVal;
    uint16_t AddCheckVal;
    AddVal = crc16_result(ReadBuff.mid(0,4), 4);
    //取长度
    AddCheckVal = (((ReadBuff[9]&0x00FF)<<8) & 0xFF00) | (ReadBuff[8]&0x00FF);
    int len = AddCheckVal;
    if(0 != len)
    {
        if(PORT_SIZE_MAX_F210 < len)
        {
            return false;
        }
        AddVal += crc16_result(ReadBuff.mid(12,len), len);
    }
    AddCheckVal = ((ReadBuff[11]<<8) & 0xFF00) | (ReadBuff[10]&0x00FF);
    if(AddVal != AddCheckVal)
    {
        return false;
    }

    return true;
}
//命令处理
QByteArray F210_CmdPacket(QByteArray LineStr,QByteArray CmdStr)
{
    QByteArray SendBuff;
    SendBuff.resize(PORT_SIZE_MAX_F210);
    int BuffCnt = 0;

    QByteArray RandNums;
    RandNums.resize(4);
    RandNums.clear();
    generateRandomNumber(RandNums, 4);
    for(int icnt=0;icnt<4;icnt++)
    {
        SendBuff[icnt] = RandNums.at(icnt);
    }
    BuffCnt += 4;
    //id
    for(int icnt=0;icnt<4;icnt++)
    {
        SendBuff[BuffCnt+icnt] = CmdStr.at(icnt);
    }
    BuffCnt += 4;
    //Length
    uint16_t Size;
    Size = LineStr.size();
    SendBuff[BuffCnt] = (Size >> 8) & 0x00FF;
    SendBuff[BuffCnt+1] = Size & 0x00FF;
    BuffCnt += 2;
    //check add
    uint16_t AddVal;
    AddVal = crc16_result(SendBuff, 4);
    BuffCnt += 2;
    // 数据
    int icnt;
    if(!LineStr.isEmpty())
    {
        for(icnt=0;icnt<LineStr.size();icnt++) {
            SendBuff[BuffCnt+icnt] = LineStr.at(icnt);
        }
        BuffCnt += icnt;
        AddVal += crc16_result(SendBuff.mid(12,Size), Size);
    }
    SendBuff[10] = (AddVal >> 8) & 0x00FF;
    SendBuff[11] = AddVal & 0x00FF;
    int StrLen = 512 - LineStr.size();
    if(StrLen>0)
    {
        RandNums.resize(StrLen);
        RandNums.clear();
        generateRandomNumber(RandNums, StrLen);

        for(icnt=0;icnt<StrLen;icnt++) {
            SendBuff[BuffCnt+icnt] = RandNums.at(icnt);
        }
    }

    if(SendBuff.size() != PORT_SIZE_MAX_F210)
    {
        return NULL;
    }

    return SendBuff;
}

//测试-写入mcu文件crc
void LipsCrc32_Calc(QByteArray CalcBuff, int CalcSize)
{
    uint32_t nCrc;
    uint32_t nTmp = 0;
    int iCnt, jCnt;

    nCrc = 0xFFFFFFFF;

    for(jCnt=0; jCnt<CalcSize; jCnt++)
    {
        nCrc ^= ((uint32_t)(CalcBuff[jCnt])&0x000000FF);

        for(iCnt=0; iCnt<4; iCnt++)
        {
            nTmp   = SERIAL_CRC32_TABLE[(uint8_t)((nCrc>>24) & 0xFF)];
            nCrc <<= 8;
            nCrc  ^= nTmp;
        }
    }

    Crc32  = nCrc;
    DatLen += CalcSize;
}

